package com.bdtop.dbl.ui.activities.device;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.DatePickerDialog;
import android.app.DatePickerDialog.OnDateSetListener;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.animation.AnimationUtils;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ZoomControls;

import com.baidu.mapapi.map.BaiduMap;
import com.baidu.mapapi.map.BaiduMap.OnMarkerClickListener;
import com.baidu.mapapi.map.BitmapDescriptor;
import com.baidu.mapapi.map.BitmapDescriptorFactory;
import com.baidu.mapapi.map.InfoWindow;
import com.baidu.mapapi.map.InfoWindow.OnInfoWindowClickListener;
import com.baidu.mapapi.map.MapStatusUpdate;
import com.baidu.mapapi.map.MapStatusUpdateFactory;
import com.baidu.mapapi.map.MapView;
import com.baidu.mapapi.map.Marker;
import com.baidu.mapapi.map.MarkerOptions;
import com.baidu.mapapi.map.Overlay;
import com.baidu.mapapi.map.OverlayOptions;
import com.baidu.mapapi.map.PolylineOptions;
import com.baidu.mapapi.model.LatLng;
import com.baidu.mapapi.overlayutil.OverlayManager;
import com.bdtop.dbl.BaseActivity;
import com.bdtop.dbl.DBLApplication;
import com.bdtop.dbl.R;
import com.bdtop.dbl.model.Track;
import com.bdtop.dbl.server.ServerApiFactory;
import com.bdtop.dbl.server.response.HistoryTrackResponse;
import com.bdtop.dbl.thirdparty.asynchttp.RequestCallback;
import com.bdtop.dbl.ui.view.TimeLineSeekBar;
import com.bdtop.dbl.ui.view.TimeLineSeekBar.OnTimeChangedListener;
import com.bdtop.dbl.ui.view.TitleBar;
import com.bdtop.dbl.utils.Constants;
import com.bdtop.dbl.utils.DBLDebug;
import com.bdtop.dbl.utils.Preferences;

@SuppressLint("SimpleDateFormat")
public class DeviceTrackActivity extends BaseActivity {

	private TitleBar mTitleBar;

	private OverlayManager overlayManager;
	List<OverlayOptions> markerOptionsList = new ArrayList<OverlayOptions>();
	private MapView mMapView;
	private LinearLayout layoutTimeBar;
	private DatePickerDialog setTimeDialog;
	private TimeLineSeekBar mTimebar;
	private BaiduMap mBaiduMap;
	private InfoWindow mInfoWindow;

	private TextView txCurrentTime;
	private Button mSetTimeBtn;

	private Date selectedDay;
	private List<Track> trackList;

	private final String MARK_INDEX = "mark_index";

	public static final long ONE_DAY_INTERVAL = 60 * 60 * 24 - 1;
	private String sign;
	private String mdn;
	private long utc1; // start time
	private long utc2; // end time

	public static final void launch(Context context) {
		Intent intent = new Intent(context, DeviceTrackActivity.class);
		context.startActivity(intent);
		((Activity) context).overridePendingTransition(R.anim.slide_in_right,
				R.anim.keep_original_state);
	}

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		setContentView(R.layout.activity_track);
		super.onCreate(savedInstanceState);
		initViews();

		sign = Preferences.getLoginSign(this);
		if(DBLApplication.getInstance().currentDi != null){
			mdn = DBLApplication.getInstance().currentDi.mdn;	
		} else {
			this.finish();
		}

		Calendar calendar = Calendar.getInstance();
		int year = calendar.get(Calendar.YEAR);
		int monthOfYear = calendar.get(Calendar.MONTH) + 1;
		int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);
		resetUtc1Utc2(year, monthOfYear, dayOfMonth);

		MapStatusUpdate mapStatusUpdate = MapStatusUpdateFactory
				.zoomTo(Constants.DEFAULT_ZOOM_LEVEL);
		mBaiduMap.animateMapStatus(mapStatusUpdate);

		loadData();
	}

	private boolean request_waiting = false;

	public void showSetTimeDialog() {
		if (setTimeDialog != null && setTimeDialog.isShowing()) {
			return;
		}
		final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		// set current time as default time
		String[] dayStringValues = sdf.format(selectedDay).split("-");
		int year = Integer.valueOf(dayStringValues[0]);
		int monthOfYear = Integer.valueOf(dayStringValues[1]) - 1;
		int dayOfMonth = Integer.valueOf(dayStringValues[2]);

		setTimeDialog = new DatePickerDialog(this, new OnDateSetListener() {
			@Override
			public void onDateSet(DatePicker view, int year, int monthOfYear,
					int dayOfMonth) {

				// part 1: to deal selected time
				resetUtc1Utc2(year, monthOfYear + 1, dayOfMonth);
				// part 2: to close date dialog
				dismissSetTimeDialog();

				loadData();
				request_waiting = true;
			}
		}, year, monthOfYear, dayOfMonth);
		setTimeDialog.show();
	}

	private void dismissSetTimeDialog() {
		if (setTimeDialog != null && setTimeDialog.isShowing()) {
			setTimeDialog.dismiss();
		}
	}

	/**
	 * 处理足迹点
	 * 
	 * @param response
	 *            足迹点数据
	 */
	private void dealHistoryTrackResponse(HistoryTrackResponse response) {
		try {
			// 清除之前地图上所有图层
			mBaiduMap.clear();
			// 重设足迹点
			trackList = response.getTrackdata();
			if (trackList == null || trackList.size() < 1) {
				DBLDebug.logd("current device hasn't any track point in setting time");
				Toast.makeText(this, response.getDesc(), Toast.LENGTH_SHORT)
						.show();
				return;
			}
			final List<LatLng> latLngList = new ArrayList<LatLng>();
			// 填充百度经纬度实体列表
			for (int i = 0; i < trackList.size(); i++) {
				Track t = trackList.get(i);
				latLngList.add(new LatLng(t.getLat(), t.getLon()));
			}

			// 时间轴当前时间之后的线，用蓝色表示
			// 注：百度PolylineOptions 只能承受最少2个，最多10000个点。
			// 移除上次的点
			overlayManager.removeFromMap();
			markerOptionsList.clear();
			// 画所有足迹点
			for (int i = 0; i < latLngList.size(); i++) {
				Bundle b = new Bundle();
				b.putInt(MARK_INDEX, i);
				int icon = R.drawable.track_point4;
				if (trackList.get(i).getAv() != 1) {// 1 基站 2 GPS 3 北斗
					icon = R.drawable.track_point3;
				}
				LatLng old = latLngList.get(i);
				LatLng fix = new LatLng(old.latitude, old.longitude);
				OverlayOptions markerOptions = new MarkerOptions()
						.perspective(false).position(fix).extraInfo(b)
						//设置zIndex 压在足迹线上面
						 .zIndex(10 + i)
						// 根据不同定位方式设置不同图标
						.icon(BitmapDescriptorFactory.fromResource(icon));
				markerOptionsList.add(markerOptions);
			}

			// 显示起点的信息并且移动到起点
			showMarkPointInfo(0);

			mHandler.postDelayed(new Runnable() {
				@Override
				public void run() {
					try {
						if(overlayManager != null){
							overlayManager.addToMap();
							overlayManager.zoomToSpan();	
						}
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}, 500);

		} catch (Exception e) {
			DBLDebug.loge("track activity - dealHistoryTrackResponse() - map error");
		}
	}

	private void toSelfLocation() {
		try {
			String[] latlng = Preferences
					.getLastSelfLocation(DeviceTrackActivity.this);
			LatLng point = new LatLng(Double.parseDouble(latlng[0]),
					Double.parseDouble(latlng[1]));
			MapStatusUpdate mapStatusUpdate = MapStatusUpdateFactory
					.newLatLng(point);
			mBaiduMap.animateMapStatus(mapStatusUpdate);
		} catch (Exception e) {
		}

	}

	private OnMarkerClickListener mOnMarkerClickListener = new OnMarkerClickListener() {

		@Override
		public boolean onMarkerClick(Marker marker) {
			Bundle b = marker.getExtraInfo();
			int index = b.getInt(MARK_INDEX);
			DBLDebug.logi("click marker index is " + index);
			// part 2: update progress on time bar
			mTimebar.updateProgressByCurrentIndex( index );
			return true;
		}
	};

	Overlay trackLineNext;
	Overlay trackLineBefore;

	/**
	 * 时间轴当前时间之前和后的线，用绿色表示之前，蓝色表示之后 。注：百度PolylineOptions 只能承受最少2个，最多10000个点。
	 */
	private void reDrawTrackLine(int index) {
		if (trackList == null || trackList.size() < 1) {
			DBLDebug.logd("current device hasn't any track point in setting time");
			Toast.makeText(this, R.string.no_track, Toast.LENGTH_SHORT).show();
			return;
		}

		List<LatLng> latLngNextList = new ArrayList<LatLng>();
		List<LatLng> latLngBeforList = new ArrayList<LatLng>();

		for (int i = 0; i < trackList.size(); i++) {
			Track t = trackList.get(i);
			if (i < index) {
				latLngBeforList.add(new LatLng(t.getLat(), t.getLon()));
			} else if (i == index) {
				latLngBeforList.add(new LatLng(t.getLat(), t.getLon()));
				latLngNextList.add(new LatLng(t.getLat(), t.getLon()));
			} else {
				latLngNextList.add(new LatLng(t.getLat(), t.getLon()));
			}
		}
		if (trackLineNext != null) {
			trackLineNext.remove();
		}
		if (latLngNextList.size() > 1) {
			OverlayOptions polylineOptions = new PolylineOptions().points(
					latLngNextList).color(Color.parseColor("#4CBDCD")).zIndex(0);
			trackLineNext = mBaiduMap.addOverlay(polylineOptions);
		}

		if (trackLineBefore != null) {
			trackLineBefore.remove();
		}
		if (latLngBeforList.size() > 1) {
			OverlayOptions polylineOptions = new PolylineOptions().points(
					latLngBeforList).color(Color.parseColor("#FF5000")).zIndex(1);
			trackLineBefore = mBaiduMap.addOverlay(polylineOptions);
		}
	}

	private LatLng showMarkPointInfo(int index) {
		// 在时间轴上选择的点在起点以前会返回-1，这个时候调整为第一个
		if (index <= 0) {
			index = 0;
		}
		if(index >= trackList.size()){
			index = trackList.size() - 1;
		}
		Track t = trackList.get(index);
		LatLng point = new LatLng(t.getLat(), t.getLon());

		String trackInfo = t.getAddrname().replace(' ', '\n');
		View view = mInflater.inflate(R.layout.infowindow_latlng_point_info,
				null);
		TextView txTrackInfo = (TextView) view.findViewById(R.id.tx_point_info);
		final String emptyInfo = Constants.EMPTY_ADDRESS_INFO;
		if (!"null".equals(trackInfo) && !emptyInfo.equals(trackInfo)) {
			DBLDebug.logd("info index" + index);
			String startStr = "";
			if (index <= 0) {
				startStr = getString(R.string.start_point);
			} else if (index >= trackList.size() - 1) {
				startStr = getString(R.string.end_point);
			}
			txTrackInfo.setText(startStr + trackInfo);
		} else {
			txTrackInfo.setText(t.getTime());
		}
//		mInfoWindow = new InfoWindow(view, point,
//				new OnInfoWindowClickListener() {
//					@Override
//					public void onInfoWindowClick() {
//						mBaiduMap.hideInfoWindow();
//					}
//				});
		
//		mInfoWindow = new InfoWindow(view, point,0);
		
		BitmapDescriptor d = BitmapDescriptorFactory.fromView(view);
		mInfoWindow = new InfoWindow( d, point, 0,
				new OnInfoWindowClickListener() {
					@Override
					public void onInfoWindowClick() {
						mBaiduMap.hideInfoWindow();
					}
				});

		mBaiduMap.showInfoWindow(mInfoWindow);
		DBLDebug.logd("move to index("+index+")!!!track");

		reDrawTrackLine(index);

		return point;
	}

	private void initViews() {
		mTitleBar = (TitleBar) findViewById(R.id.title_bar);
		mTitleBar.setTitle(R.string.trajectory_title);
		mTitleBar.setBelongActivity(this);

		mMapView = (MapView) findViewById(R.id.bmap_view);

		hideZoomController();

		mBaiduMap = mMapView.getMap();
		// 添加点击足迹点的回调
		mBaiduMap.setOnMarkerClickListener(mOnMarkerClickListener);
		// 为了让所有足迹点可以在屏幕里面都看的见
		overlayManager = new OverlayManager(mBaiduMap) {

			@Override
			public boolean onMarkerClick(Marker arg0) {
				return false;
			}

			@Override
			public List<OverlayOptions> getOverlayOptions() {
				return markerOptionsList;
			}
		};

		mSetTimeBtn = (Button) findViewById(R.id.select_time_btn);

		mSetTimeBtn.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View arg0) {
				showSetTimeDialog();
			}
		});

		layoutTimeBar = (LinearLayout) findViewById(R.id.layout_timebar);
		layoutTimeBar.setVisibility(View.GONE);

		mTimebar = (TimeLineSeekBar) findViewById(R.id.seekbar_timeline);
		mTimebar.setOnTimeChangedListener(new OnTimeChangedListener() {
			@Override
			public void onTimeChanged(int currentIndex) {
				// 当足迹轴拖动到所有点以前，便为NONE_SELECTED_POINT
				if (currentIndex == TimeLineSeekBar.NONE_SELECTED_POINT) {
					// 如果足迹点集合有内容，便设置为第一个点
					if(trackList.size() > 0)
						currentIndex = 0;
				}
					LatLng point = showMarkPointInfo(currentIndex);
					MapStatusUpdate mapStatusUpdate = MapStatusUpdateFactory
							.newLatLng(point);
					mBaiduMap.animateMapStatus(mapStatusUpdate);
				
				mTimebar.invalidate();
			}
		});

		// add
		mMapView.setVisibility(View.GONE);

		txCurrentTime = (TextView) findViewById(R.id.text_current_time);
		txCurrentTime.setVisibility(View.GONE);

		txWaitingMessage = (TextView) findViewById(R.id.tx_waiting_message);
	}

	private void resetUtc1Utc2(int year, int monthOfYear, int dayOfMonth) {
		String selectedStringDate = year + "-" + monthOfYear + "-" + dayOfMonth;
		txCurrentTime.setText(selectedStringDate);
		DBLDebug.logi("selected track time is " + selectedStringDate);
		try {
			selectedDay = new SimpleDateFormat("yyyy-MM-dd")
					.parse(selectedStringDate);
		} catch (ParseException e1) {
		}
		utc1 = selectedDay.getTime() / 1000;

		utc2 = utc1 + ONE_DAY_INTERVAL;
	}

	private void loadData() {
		if (request_waiting)
			return;

		DBLDebug.logd("get History track list");
		setAndShowWaitingMessage(R.string.wating_search);
		ServerApiFactory.getApiImpl().getHistoryTrack(sign, mdn, utc1, utc2,
				new RequestCallback() {
					@Override
					public void onSuccess(String rawData, Object response) {
						mTimebar.setProgress(0);
						request_waiting = false;
						txWaitingMessage.setVisibility(View.GONE);
						// add
						txCurrentTime.setVisibility(View.VISIBLE);
						mMapView.setVisibility(View.VISIBLE);
						HistoryTrackResponse htResponse = (HistoryTrackResponse) response;

						if (Constants.REQUEST_SUCCESS.equals(htResponse
								.getStatus())) {
							dealHistoryTrackResponse(htResponse);
							if (trackList != null) {
								mTimebar.initTimePoint(trackList, utc1 * 1000);
								mTimebar.invalidate();
							}
							layoutTimeBar.setVisibility(View.VISIBLE);
							layoutTimeBar.startAnimation(AnimationUtils
									.loadAnimation(DeviceTrackActivity.this,
											R.anim.fade_in));
						} else {

							showToast(htResponse.getDesc());
							//
							if (trackList == null) {
								toSelfLocation();
							}
							layoutTimeBar.setVisibility(View.GONE);
						}
					}

					@Override
					public void onError(int statusCode, Throwable e,
							String rawData) {
						request_waiting = false;
						// dismissDialog();
						txWaitingMessage.setText(R.string.net_error);
						// add
						mMapView.setVisibility(View.VISIBLE);
						toSelfLocation();
						// showToast(R.string.net_error);
						layoutTimeBar.setVisibility(View.GONE);
					}
				});
	}

	private void hideZoomController() {
		int count = mMapView.getChildCount();
		View zoomView = null;

		for (int i = 0; i < count; i++) {
			View child = mMapView.getChildAt(i);
			if (child instanceof ZoomControls) {
				zoomView = child;
				break;
			}
		}
		zoomView.setVisibility(View.GONE);
	}

	@Override
	protected void onResume() {
		super.onResume();
		mMapView.onResume();
	}

	@Override
	protected void onPause() {
		super.onPause();
		mMapView.onPause();
	}

	@Override
	protected void onDestroy() {
		super.onDestroy();
		mMapView.onDestroy();
	}

	@Override
	public void finish() {
		super.finish();
		overridePendingTransition(R.anim.keep_original_state,
				R.anim.slide_out_right);
	}
}
